#include "videowindow.h"
#include "ui_videowindow.h"
#include <QDateTime>
#include <QFileDialog>
#include <QUrl>
#include <QMessageBox>
#include <thread>
#include <functional>
#include <iostream>
#include <iostream>
#include <chrono>
#include "toast.h"
#include "urldialog.h"
#include "ffmsg_global.h"
#include "toast.h"
#include "urldialog.h"
#include "globalresource.h"


int64_t get_ms()
{
//#ifdef  Debug_Falg //循环
//    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
//#endif
    std::chrono::milliseconds ms = std::chrono::duration_cast< std::chrono::milliseconds >(
                                       std::chrono::system_clock::now().time_since_epoch()
                                   );
    return ms.count();
}

static int is_realtime(const char *url)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(   !strcmp(url, "rtp")
          || !strcmp(url, "rtsp")
          || !strcmp(url, "sdp")
          || !strcmp(url, "udp")
          || !strcmp(url, "rtmp")
      ) {
        return 1;
    }
    return 0;
}
VideoWindow::VideoWindow(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::VideoWindow)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    ui->setupUi(this);

    Init();
    ConnectSignalSlots();

}

VideoWindow::~VideoWindow()
{
    delete ui;
}

bool VideoWindow::Init()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    SlotStopFinished();
    ui->playList->Init();

    ui->PlayOrPauseBtn->setStyleSheet("QPushButton{background-color: rgba(255, 255, 255, 0);border:0px;};QToolTip{color: white;}");
    ui->StopBtn->setStyleSheet("QPushButton{background-color: rgba(255, 255, 255, 0);border:0px;};QToolTip{color: white;}");
    ui->BackwardBtn->setStyleSheet("QPushButton{background-color: rgba(255, 255, 255, 0);border:0px;};QToolTip{color: white;}");
    ui->ForwardBtn->setStyleSheet("QPushButton{background-color: rgba(255, 255, 255, 0);border:0px;};QToolTip{color: white;}");
    ui->speedBtn->setStyleSheet("QPushButton{background-color: rgba(255, 255, 255, 0);border:0px;};QToolTip{color: white;}");

    ui->VolumeBtn->setStyleSheet("background-color: rgba(255, 255, 255, 0);border:0px;");
    ui->curPosition->setStyleSheet("background-color: rgba(255, 255, 255, 0);border:0px;");
    ui->totalDuration->setStyleSheet("background-color: rgba(255, 255, 255, 0);border:0px;");

    ui->addFile->setStyleSheet("background-color: rgba(255, 255, 255, 0);border: 2px solid red;");
    ui->addAddress->setStyleSheet("background-color: rgba(255, 255, 255, 0);border: 2px solid red;");
    ui->deleteThis->setStyleSheet("background-color: rgba(255, 255, 255, 0);border: 2px solid red;");
    ui->clearOut->setStyleSheet("background-color: rgba(255, 255, 255, 0);border: 2px solid red;");

    ui->PlayOrPauseBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/play.png"));
    ui->StopBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/end.png"));
    ui->ForwardBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/after.png"));
    ui->BackwardBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/before.png"));
    ui->VolumeBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/aac_open.png"));

    ui->PlayOrPauseBtn->setToolTip("播放");
    ui->StopBtn->setToolTip("终止");
    ui->BackwardBtn->setToolTip("上一个");
    ui->ForwardBtn->setToolTip("下一个");
    ui->speedBtn->setToolTip("倍速");

}

/**
 * @brief VideoWindow::ConnectSignalSlots 连接信号与槽，用于实现不同组件间的通信
 * @return 固定返回true，后续可根据实际连接情况修改返回值
 */
bool VideoWindow::ConnectSignalSlots()
{
    /*添加文件、添加地址、移除文件、清空文件*/
    connect(this, &VideoWindow::AddFile, ui->playList, &Playlist::AddFile);
    connect(this, &VideoWindow::AddUrl, ui->playList, &Playlist::AddUrl);
    connect(this, &VideoWindow::RemoveFile, ui->playList, &Playlist::RemoveFile);
    connect(this, &VideoWindow::clear, ui->playList, &Playlist::clear);

    // 当 Playlist 发出 SigPlay 信号时，触发 VideoWindow 的 play 槽函数
    connect(ui->playList, &Playlist::SigPlay, this, &VideoWindow::play);
    // 当 VideoWindow 发出 sig_stopped 信号时，触发自身的 stop 槽函数
    connect(this, &VideoWindow::sig_stopped, this, &VideoWindow::stop);

    // 设置更新当前播放位置的回调，当发出 sig_updateCurrentPosition 信号时，触发 on_updateCurrentPosition 槽函数
    connect(this, &VideoWindow::sig_updateCurrentPosition, this, &VideoWindow::on_updateCurrentPosition);

    // 当播放进度条发出 SigCustomSliderValueChanged 信号时，触发 on_playSliderValueChanged 槽函数
    connect(ui->PlaySlider, &CustomSlider::SigCustomSliderValueChanged, this, &VideoWindow::on_playSliderValueChanged);
    // 当音量进度条发出 SigCustomSliderValueChanged 信号时，触发 on_volumeSliderValueChanged 槽函数
    connect(ui->VolumeSlider, &CustomSlider::SigCustomSliderValueChanged, this, &VideoWindow::on_volumeSliderValueChanged);
    // 当发出 sig_updateAudioCacheDuration 信号时，触发 on_UpdateAudioCacheDuration 槽函数
    connect(this, &VideoWindow::sig_updateAudioCacheDuration, this, &VideoWindow::on_UpdateAudioCacheDuration);
    // 当发出 sig_updateVideoCacheDuration 信号时，触发 on_UpdateVideoCacheDuration 槽函数
    connect(this, &VideoWindow::sig_updateVideoCacheDuration, this, &VideoWindow::on_UpdateVideoCacheDuration);
    // 当发出 sig_updatePlayOrPause 信号时，触发 on_updatePlayOrPause 槽函数
    connect(this, &VideoWindow::sig_updatePlayOrPause, this, &VideoWindow::on_updatePlayOrPause);

    // 设置播放进度条的最小值为 0
    ui->PlaySlider->setMinimum(0);
    // 定义播放进度条的最大值
    play_slider_max_value = 6000;
    // 设置播放进度条的最大值
    ui->PlaySlider->setMaximum(play_slider_max_value);

    // 设置音量进度条的最小值为 0
    ui->VolumeSlider->setMinimum(0);
    // 设置音量进度条的最大值为 100
    ui->VolumeSlider->setMaximum(100);
    // 初始化音量进度条的值为 50
    ui->VolumeSlider->setValue(50);

    // toast提示不能直接在非ui线程显示，所以通过信号槽的方式触发提示
    // 自定义信号槽变量类型要注册，参考:https://blog.csdn.net/Larry_Yanan/article/details/127686354
    // 注册 Toast::Level 类型，使其能在信号槽中传递
    qRegisterMetaType<Toast::Level>("Toast::Level");
    // 当发出 sig_showTips 信号时，触发 on_showTips 槽函数
    connect(this, &VideoWindow::sig_showTips, this, &VideoWindow::on_showTips);
    // 注册 int64_t 类型，使其能在信号槽中传递
    qRegisterMetaType<int64_t>("int64_t");

    return true;
}

/**
 * @brief VideoWindow::message_loop 消息循环函数，用于处理 MediaPlayer 发送的消息
 * @param arg 传入的参数，通常为 MediaPlayer 指针
 * @return 线程退出时返回 0
 */
int VideoWindow::message_loop(void *arg)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    QString tips;
    // 将传入的参数转换为 MediaPlayer 指针
    MediaPlayer *mp = (MediaPlayer *)arg;
    // 进入线程循环
    while (1) {
        AVMessage msg;
        // 从消息队列中获取消息，0 表示非阻塞模式，在此线程可以做其他监测任务
        int retval = mp->ijkmp_get_msg(&msg, 0);
        if (retval < 0) {
            // -1 表示要退出线程循环
            break;
        }
        if(retval != 0) {
            // 根据消息类型进行不同处理
            switch (msg.what) {
                case FFP_MSG_FLUSH:
                    // 处理刷新消息
                    break;
                case FFP_MSG_PREPARED:
                    // 处理播放器准备完成消息
                    // 启动播放器
                    mp->ijkmp_start();
                    //            ui->playOrPauseBtn->setText("暂停");
                    break;
                case FFP_MSG_FIND_STREAM_INFO:
                    // 处理流信息查找完成消息
                    // 获取视频总时长
                    getTotalDuration();
                    break;
                case FFP_MSG_PLAYBACK_STATE_CHANGED:
                    // 处理播放状态改变消息
                    if(mp_->ijkmp_get_state() == MP_STATE_STARTED) {
                        // 发送播放状态更新信号（开始播放）
                        emit sig_updatePlayOrPause(MP_STATE_STARTED);
                    }
                    if(mp_->ijkmp_get_state() == MP_STATE_PAUSED) {
                        // 发送播放状态更新信号（暂停播放）
                        emit sig_updatePlayOrPause(MP_STATE_PAUSED);
                    }
                    break;
                case FFP_MSG_SEEK_COMPLETE:
                    // 处理Seek操作完成消息
                    req_seeking_ = false;
                    //             startTimer();
                    break;
                case FFP_MSG_SCREENSHOT_COMPLETE:
                    // 处理截屏完成消息
                    if(msg.arg1 == 0 ) {
                        // 截屏成功提示
                        tips.sprintf("截屏成功,存储路径:%s", (char *)msg.obj);
                        emit sig_showTips(Toast::INFO, tips);
                    } else {
                        // 截屏失败提示
                        tips.sprintf("截屏失败, ret:%d", msg.arg1);
                        emit sig_showTips(Toast::WARN, tips);
                    }
                    req_screenshot_ = false;
                    break;
                case FFP_MSG_PLAY_FNISH:
                    // 处理播放结束消息
                    tips.sprintf("播放完毕");
                    emit sig_showTips(Toast::INFO, tips);
                    // 发送停止信号，触发停止函数
                    emit sig_stopped();
                    break;
                default:
                    if(retval != 0) {
                        // 处理未预期的消息
                    }
                    break;
            }
        }
        // 释放消息资源
        msg_free_res(&msg);
        // 线程休眠 20 毫秒
        std::this_thread::sleep_for(std::chrono::milliseconds(20));
        // 获取缓存时长并进行相关处理
        reqUpdateCacheDuration();
        // 获取当前播放位置
        reqUpdateCurrentPosition();
    }
    return 0;
}

int VideoWindow::OutputVideo(const Frame *frame)
{
//#ifdef  Debug_Falg//循环
//    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
//#endif
    // 调用显示控件
    return ui->ShowWid->Draw(frame);// frame：用于缓存解码后的音视频帧信息结构体
}

void VideoWindow::resizeEvent(QResizeEvent *event)
{
    resizeUI();
}

void VideoWindow::resizeUI()
{
//    int width = this->width();
//    int height = this->height();
//    // 获取当前ctrlwidget的位置
//    QRect rect =   ui->ctrlBar->geometry();
//    rect.setY(height - ui->menuBar->height() - rect.height());
//    rect.setWidth(width);
//    ui->ctrlBar->setGeometry(rect);
//    // 设置setting和listbutton的位置
//    rect = ui->settingBtn->geometry();
//    // 获取 ctrlBar的大小 计算list的 x位置
//    int  x1 =  ui->ctrlBar->width() - rect.width() - rect.width() / 8 * 2;
//    ui->listBtn->setGeometry(x1, rect.y(), rect.width(), rect.height());
//    // 设置setting button的位置，在listbutton左侧
//    rect = ui->listBtn->geometry();
//    x1 = rect.x() - rect.width() - rect.width() / 8 ;
//    ui->settingBtn->setGeometry(x1, rect.y(), rect.width(), rect.height());
//    // 设置 显示画面
//    if(is_show_file_list_) {
//        width = this->width() - ui->playList->width();
//    } else {
//        width = this->width();
//    }
//    height = this->height() - ui->ctrlBar->height() - ui->menuBar->height();
//    //    int y1 = ui->menuBar->height();
//    int y1 = 0;
//    ui->ShowWid->setGeometry(0, y1, width, height);
//    // 设置文件列表 list
//    if(is_show_file_list_) {
//        ui->playList->setGeometry(ui->ShowWid->width(), y1, ui->playList->width(), height);
//    }
//    // 设置播放进度条的长度，设置成和显示控件宽度一致
//    rect = ui->playSlider->geometry();
//    width = ui->ShowWid->width() - 5 - 5;
//    rect.setWidth(width);
//    ui->playSlider->setGeometry(5, rect.y(), rect.width(), rect.height());
//    // 设置音量条位置
//    x1 = this->width() - 5 - ui->volumeSlider->width();
//    rect = ui->volumeSlider->geometry();
//    ui->volumeSlider->setGeometry(x1, rect.y(), rect.width(), rect.height());
}

void VideoWindow::closeEvent(QCloseEvent *event)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    //添加退出事件处理
    // 弹出一个确认对话框
    QMessageBox::StandardButton reply;
    reply = QMessageBox::question(this, "确认退出", "您确定要退出吗？",
                                  QMessageBox::Yes | QMessageBox::No);

    if (reply == QMessageBox::Yes) {
        // 用户选择退出，执行清理操作
        stop(); //先关闭现有的播放器
        event->accept(); // 接受关闭事件，窗口关闭
    } else {
        // 用户选择不退出，忽略关闭事件
        event->ignore(); // 忽略关闭事件，窗口保持打开
    }
}

void VideoWindow::on_UpdateAudioCacheDuration(int64_t duration)
{
//    ui->audioBufEdit->setText(QString("%1ms").arg(duration));
}

void VideoWindow::on_UpdateVideoCacheDuration(int64_t duration)
{
//    ui->videoBufEdit->setText(QString("%1ms").arg(duration));
}

void VideoWindow::on_openFile()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    QUrl url = QFileDialog::getOpenFileName(this, QStringLiteral("选择路径"), QDir::homePath(),
                                            nullptr,
                                            nullptr, QFileDialog::DontUseCustomDirectoryIcons);
    if(!url.toString().isEmpty()) {
        QFileInfo fileInfo(url.toString());
        // 停止状态下启动播放
        int ret = play(fileInfo.filePath().toStdString().c_str());
        // 并把该路径加入播放列表
        ui->playList->OnAddFile(url.toString());
    }
}

void VideoWindow::on_openNetworkUrl()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    UrlDialog urlDialog(this);
    int nResult = urlDialog.exec();
    if(nResult == QDialog::Accepted) {
        //
        QString url = urlDialog.GetUrl();
        if(!url.isEmpty()) {
            //            emit SigAddFile(url);
            ui->playList->AddNetworkUrl(url);
            int ret = play(url.toStdString());
        }
    } else {
    }
}

void VideoWindow::resizeCtrlBar()
{
}

void VideoWindow::resizeDisplayAndFileList()
{
}

int VideoWindow::seek(int cur_valule)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
        // 打印当前的值
        double percent = cur_valule * 1.0 / play_slider_max_value;
        req_seeking_ = true;
        int64_t milliseconds = percent * total_duration_;
        mp_->ijkmp_seek_to(milliseconds);
        return 0;
    } else {
        return -1;
    }
}

int VideoWindow::fastForward(long inrc)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
        mp_->ijkmp_forward_to(inrc);
        return 0;
    } else {
        return -1;
    }
}

int VideoWindow::fastBack(long inrc)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
        mp_->ijkmp_back_to(inrc);
        return 0;
    } else {
        return -1;
    }
}

void VideoWindow::getTotalDuration()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
        total_duration_ = mp_->ijkmp_get_duration();
        // 更新信息
        // 当前播放位置，总时长
        long seconds = total_duration_ / 1000;
        int hour = int(seconds / 3600);
        int min = int((seconds - hour * 3600) / 60);
        int sec = seconds % 60;
        QTime TotalTime(hour, min, sec);

        ui->totalDuration->setTime(TotalTime);
    }
}

void VideoWindow::reqUpdateCurrentPosition()
{
//#ifdef  Debug_Falg//循环
//    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
//#endif
    int64_t cur_time = get_ms();
    if(cur_time - pre_get_cur_pos_time_ > 500) {
        pre_get_cur_pos_time_ = cur_time;
        // 播放器启动,并且不是请求seek的时候才去读取最新的播放位置
        if(mp_ && !req_seeking_) {
            current_position_ = mp_->ijkmp_get_current_position();
            emit sig_updateCurrentPosition(current_position_);
        }
    }
}

void VideoWindow::reqUpdateCacheDuration()
{
//#ifdef  Debug_Falg//循环
//    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
//#endif
    int64_t cur_time = get_ms();
    if(cur_time - pre_get_cache_time_ > 500) {
        pre_get_cache_time_ = cur_time;
        if(mp_) {
            audio_cache_duration =  mp_->ijkmp_get_property_int64(FFP_PROP_INT64_AUDIO_CACHED_DURATION, 0);
            video_cache_duration  =  mp_->ijkmp_get_property_int64(FFP_PROP_INT64_VIDEO_CACHED_DURATION, 0);
            emit sig_updateAudioCacheDuration(audio_cache_duration);
            emit sig_updateVideoCacheDuration(video_cache_duration);
            //是否触发变速播放取决于是不是实时流，这里由业务判断，目前主要是判断rtsp、rtmp、rtp流为直播流，有些比较难判断，比如httpflv既可以做直播也可以是点播
            if(real_time_ ) {
                if(audio_cache_duration > max_cache_duration_ + network_jitter_duration_) {
                    // 请求开启变速播放
                    mp_->ijkmp_set_playback_rate(accelerate_speed_factor_);
                    is_accelerate_speed_ = true;
                }
                if(is_accelerate_speed_ && audio_cache_duration < max_cache_duration_) {
                    mp_->ijkmp_set_playback_rate(normal_speed_factor_);
                    is_accelerate_speed_ = false;
                }
            }
        }
    }
}

bool VideoWindow::play(std::string url)
{
//#ifdef  Debug_Falg
//    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
//#endif
    int ret = 0;
    // 如果本身处于播放状态则先停止原有的播放
    if(mp_) {
        stop();
    }
    // 1. 先检测mp是否已经创建
    real_time_ = is_realtime(url.c_str());
    is_accelerate_speed_ = false;//是否开启变速播放
    mp_ = new MediaPlayer();
    //1.1 创建
    ret = mp_-> ijkmp_create(std::bind(&VideoWindow::message_loop, this, std::placeholders::_1));
    if(ret < 0) {
        delete mp_;
        mp_ = NULL;
        return false;
    }
    // mp_->AddVideoRefreshCallback(std::bind(&VideoWindow::OutputVideo, this,
    //                                        std::placeholders::_1));
    mp_->AddVideoRefreshCallback([this](const Frame *frame) {
            return this->OutputVideo(frame);
        });//使用lambda表达式优化
    // 1.2 设置url
    mp_->ijkmp_set_data_source(url.c_str());
    mp_->ijkmp_set_playback_volume(ui->VolumeSlider->value());
    
    // 1.3 准备工作
    ret = mp_->ijkmp_prepare_async();
    if(ret < 0) {
        delete mp_;
        mp_ = NULL;
        return false;
    }
    ui->ShowWid->StartPlay();
//    startTimer();
    return true;
}

void VideoWindow::on_updatePlayOrPause(int state)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(state == MP_STATE_STARTED) {
        ui->PlayOrPauseBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/stop.png"));
        ui->PlayOrPauseBtn->setToolTip("暂停");
    } else  {
        ui->PlayOrPauseBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/play.png"));
        ui->PlayOrPauseBtn->setToolTip("播放");
    }
}

void VideoWindow::onTimeOut()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
        //        reqUpdateCurrentPosition();
    }
}

void VideoWindow::on_playSliderValueChanged(int value)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    seek(value);
}

void VideoWindow::on_volumeSliderValueChanged(int value)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
        mp_->ijkmp_set_playback_volume(value);
    }
}

bool VideoWindow::stop()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
//        stopTimer();
        mp_->ijkmp_stop();
        mp_->ijkmp_destroy();
        delete mp_;
        mp_ = NULL;
        real_time_ = 0;
        is_accelerate_speed_ = false;
        ui->ShowWid->StopPlay();        // 停止渲染，后续刷黑屏
        ui->PlayOrPauseBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/play.png"));
        ui->PlayOrPauseBtn->setToolTip("播放");
        return 0;
    } else {
        return -1;
    }
}


void VideoWindow::startTimer()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(play_time_) {
        play_time_->stop();
        delete play_time_;
        play_time_ = nullptr;
    }
    play_time_ = new QTimer();
    play_time_->setInterval(1000);  // 1秒触发一次
    connect(play_time_, SIGNAL(timeout()), this, SLOT(onTimeOut()));
    play_time_->start();
}

void VideoWindow::stopTimer()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(play_time_) {
        play_time_->stop();
        delete play_time_;
        play_time_ = nullptr;
    }
}

bool VideoWindow::resume()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
        mp_->ijkmp_start();
        return 0;
    } else {
        return -1;
    }
}

bool VideoWindow::pause()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
        mp_->ijkmp_pause();
        return 0;
    } else {
        return -1;
    }
}

void VideoWindow::on_showTips(Toast::Level leve, QString tips)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    Toast::instance().show(leve, tips);
}

void VideoWindow::on_bufDurationBox_currentIndexChanged(int index)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    switch (index) {
        case 0:
            max_cache_duration_ = 30;
            break;
        case 1:
            max_cache_duration_ = 100;
            break;
        case 2:
            max_cache_duration_ = 200;
            break;
        case 3:
            max_cache_duration_ = 400;
            break;
        case 4:
            max_cache_duration_ = 600;
            break;
        case 5:
            max_cache_duration_ = 800;
            break;
        case 6:
            max_cache_duration_ = 1000;
            break;
        case 7:
            max_cache_duration_ = 2000;
            break;
        case 8:
            max_cache_duration_ = 4000;
            break;
        default:
            break;
    }
}

void VideoWindow::on_jitterBufBox_currentIndexChanged(int index)
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    switch (index) {
        case 0:
            max_cache_duration_ = 30;
            break;
        case 1:
            max_cache_duration_ = 100;
            break;
        case 2:
            max_cache_duration_ = 200;
            break;
        case 3:
            max_cache_duration_ = 400;
            break;
        case 4:
            max_cache_duration_ = 600;
            break;
        case 5:
            max_cache_duration_ = 800;
            break;
        case 6:
            max_cache_duration_ = 1000;
            break;
        case 7:
            max_cache_duration_ = 2000;
            break;
        case 8:
            max_cache_duration_ = 4000;
            break;
        default:
            break;
    }
}


void VideoWindow::on_PlayOrPauseBtn_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif

    bool ret = false;
    if(!mp_) {

        std::string url = ui->playList->GetCurrentUrl();
        if(!url.empty()) {
            // 停止状态下启动播放
            ret = play(url);
        }
    } else {

        if(mp_->ijkmp_get_state() == MP_STATE_STARTED) {
            // 设置为暂停暂停
            mp_->ijkmp_pause();
            //            ui->playOrPauseBtn->setText("播放");
        } else if(mp_->ijkmp_get_state() == MP_STATE_PAUSED) {
            // 恢复播放
            mp_->ijkmp_start();
            //            ui->playOrPauseBtn->setText("暂停");
        }
    }
}

void VideoWindow::on_StopBtn_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    stop();
}

void VideoWindow::on_BackwardBtn_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    // 停止当前的播放，然后播放下一个，这里就需要播放列表配合
    //获取前一个播放的url 并将对应的url选中
    std::string url = ui->playList->GetPrevUrlAndSelect();
    if(!url.empty()) {
        play(url);
    } else {
        emit sig_showTips(Toast::ERROR, "没有可以播放的URL");
    }
}

void VideoWindow::on_ForwardBtn_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    std::string url = ui->playList->GetNextUrlAndSelect();
    if(!url.empty()) {
        play(url);
    } else {
        emit sig_showTips(Toast::ERROR, "没有可以播放的URL");
    }
}

void VideoWindow::on_speedBtn_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(mp_) {
        // 先获取当前的倍速,每次叠加0.5, 支持0.5~2.0倍速
        float rate =  mp_->ijkmp_get_playback_rate() + 0.5;
        if(rate > 2.0) {
            rate = 0.5;
        }
        mp_->ijkmp_set_playback_rate(rate);
        ui->speedBtn->setText(QString("倍速:%1").arg(rate));
    }
}

void VideoWindow::on_VolumeBtn_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    if(state_volume)
    {
        // 将音量按钮图标设置为正常音量图标
        ui->VolumeBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/aac_open.png"));
        state_volume = false;
    }else
    {
        // 将音量按钮图标设置为静音图标
        ui->VolumeBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/aac_close.png"));
        state_volume = true;
    }
}

void VideoWindow::on_addFile_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    emit AddFile();
}

void VideoWindow::on_addAddress_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    emit AddUrl();
}

void VideoWindow::on_deleteThis_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    emit RemoveFile();
}

void VideoWindow::on_clearOut_clicked()
{
#ifdef  Debug_Falg
    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
#endif
    emit clear();
}

void VideoWindow::SlotStopFinished()
{
//#ifdef  Debug_Falg
//    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
//#endif
    // 将播放进度条的值设置为 0，表示播放进度归零
    ui->PlaySlider->setValue(0);
    // 创建一个表示 0 时 0 分 0 秒的 QTime 对象
    QTime StopTime(0, 0, 0);
    // 将总播放时间显示设置为 0
    ui->totalDuration->setTime(StopTime);
    // 将当前播放时间显示设置为 0
    ui->curPosition->setTime(StopTime);
    // 将播放/暂停按钮的图标设置为播放图标
    ui->PlayOrPauseBtn->setIcon(QIcon(":/Resources/MainWindow/VideoWindow/play.png"));
    // 将播放/暂停按钮的工具提示设置为“播放”
    ui->PlayOrPauseBtn->setToolTip("播放");
}


void VideoWindow::on_updateCurrentPosition(long position)
{
//#ifdef  Debug_Falg//循环
//    qDebug() << "The name is : <" << __func__ << "> The file is :<" << __FILE__ << ">Thread is <" << QThread::currentThreadId();
//#endif
    // 更新信息
    // 当前播放位置，总时长
    long seconds = position / 1000;
    int hour = int(seconds / 3600);
    int min = int((seconds - hour * 3600) / 60);
    int sec = seconds % 60;

    QTime TotalTime(hour, min, sec);

    //QString格式化arg前面自动补0
    if((position <=  total_duration_)   // 如果不是直播，那播放时间该<= 总时长
       || (total_duration_ == 0)) { // 如果是直播，此时total_duration_为0
        ui->curPosition->setTime(TotalTime);
    }
    // 更新进度条
    if(total_duration_ > 0) {
        int pos = current_position_ * 1.0 / total_duration_ * ui->PlaySlider->maximum();
        ui->PlaySlider->setValue(pos);
//        ui->PlaySlider->setValue(nSeconds * 1.0 / m_nTotalPlaySeconds * MAX_SLIDER_VALUE);
    }
}








